package com.xiashitech.agent.instrumentation.base.context.bridge;

import com.xiashitech.agent.instrumentation.base.context.XSContext;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.baggage.BaggageEntry;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.baggage.BaggageEntryMetadata;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.internal.ImmutableKeyValuePairs;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Immutable
final class BridgeImmutableBaggage extends ImmutableKeyValuePairs<String, BaggageEntry> implements BridgeBaggage {
    private static final BridgeBaggage EMPTY = (new Builder()).build();

    private BridgeImmutableBaggage(Object[] data) {
        super(data, Comparator.naturalOrder());
    }

    static BridgeBaggage empty() {
        return EMPTY;
    }

    static BridgeBaggageBuilder builder() {
        return new Builder();
    }

    @Nullable
    public String getEntryValue(String entryKey) {
        BaggageEntry entry = this.get(entryKey);
        return entry != null ? entry.getValue() : null;
    }

    public BridgeBaggageBuilder toBuilder() {
        return new Builder(new ArrayList(this.data()));
    }

    private static BridgeBaggage sortAndFilterToBaggage(Object[] data) {
        return new BridgeImmutableBaggage(data);
    }

    @Override
    public XSContext storeInContextForConfluence(XSContext context) {
        throw new UnsupportedOperationException();
    }

    static class Builder implements BridgeBaggageBuilder {
        private final List<Object> data;

        Builder() {
            this.data = new ArrayList();
        }

        Builder(List<Object> data) {
            this.data = data;
        }

        public BridgeBaggageBuilder put(String key, String value, BaggageEntryMetadata entryMetadata) {
            if (key != null && value != null && entryMetadata != null) {
                this.data.add(key);
                this.data.add(BridgeImmutableEntry.create(value, entryMetadata));
                return this;
            } else {
                return this;
            }
        }

        public BridgeBaggageBuilder remove(String key) {
            if (key == null) {
                return this;
            } else {
                this.data.add(key);
                this.data.add(null);
                return this;
            }
        }

        public BridgeBaggage build() {
            return BridgeImmutableBaggage.sortAndFilterToBaggage(this.data.toArray());
        }
    }
}
